优化

FFIB 5 lat temu
rodzic
commit
b1ab7e9857

+ 1 - 0
package.json

@@ -55,6 +55,7 @@
55 55
     "js-cookie": "2.2.0",
56 56
     "jsonlint": "1.6.3",
57 57
     "jszip": "3.2.1",
58
+    "mathjs": "^7.0.0",
58 59
     "normalize.css": "7.0.0",
59 60
     "nprogress": "0.2.0",
60 61
     "path-to-regexp": "2.4.0",

+ 173 - 0
src/api/live.js

@@ -0,0 +1,173 @@
1
+import request from '@/utils/request'
2
+import store from '@/store'
3
+import qs from 'qs'
4
+
5
+export function fetchOrderList(data) {
6
+  if (data === undefined) {
7
+    data = {}
8
+  }
9
+  data['admin_id'] = store.getters.token
10
+  return request({
11
+    url: '/admin/live/order/list',
12
+    method: 'post',
13
+    data: qs.stringify(data)
14
+  })
15
+}
16
+
17
+export function deliveryOrder(data) {
18
+  if (data === undefined) {
19
+    data = {}
20
+  }
21
+  data['admin_id'] = store.getters.token
22
+  data['delivery_id'] = 'SF'
23
+  data['biz_id'] = '0103586950'
24
+  return request({
25
+    url: '/admin/live/order/delivery',
26
+    method: 'post',
27
+    data: qs.stringify(data)
28
+  })
29
+}
30
+
31
+export function fetchRoomList(data) {
32
+  if (data === undefined) {
33
+    data = {}
34
+  }
35
+  data['admin_id'] = store.getters.token
36
+  return request({
37
+    url: '/admin/live/room/list',
38
+    method: 'post',
39
+    data: qs.stringify(data)
40
+  })
41
+}
42
+
43
+export function refreshWxRoomList(data) {
44
+  if (data === undefined) {
45
+    data = {}
46
+  }
47
+  data['admin_id'] = store.getters.token
48
+  return request({
49
+    url: '/admin/live/wx/room/list',
50
+    method: 'post',
51
+    data: qs.stringify(data)
52
+  })
53
+}
54
+
55
+export function fetchGoodsList(data) {
56
+  if (data === undefined) {
57
+    data = {}
58
+  }
59
+  data['admin_id'] = store.getters.token
60
+  return request({
61
+    url: '/admin/live/goods/list',
62
+    method: 'post',
63
+    data: qs.stringify(data)
64
+  })
65
+}
66
+
67
+export function createGoods(data) {
68
+  if (data === undefined) {
69
+    data = {}
70
+  }
71
+  data['admin_id'] = store.getters.token
72
+  return request({
73
+    url: '/admin/live/goods/create',
74
+    method: 'post',
75
+    data: qs.stringify(data)
76
+  })
77
+}
78
+
79
+export function updateGoods(data) {
80
+  if (data === undefined) {
81
+    data = {}
82
+  }
83
+  data['admin_id'] = store.getters.token
84
+  return request({
85
+    url: '/admin/live/goods/update',
86
+    method: 'post',
87
+    data: qs.stringify(data)
88
+  })
89
+}
90
+
91
+export function auditGoods(data) {
92
+  if (data === undefined) {
93
+    data = {}
94
+  }
95
+  data['admin_id'] = store.getters.token
96
+  return request({
97
+    url: '/admin/live/goods/audit',
98
+    method: 'post',
99
+    data: qs.stringify(data)
100
+  })
101
+}
102
+
103
+export function deleteGoods(data) {
104
+  if (data === undefined) {
105
+    data = {}
106
+  }
107
+  data['admin_id'] = store.getters.token
108
+  return request({
109
+    url: '/admin/live/goods/delete',
110
+    method: 'post',
111
+    data: qs.stringify(data)
112
+  })
113
+}
114
+
115
+export function fetchRoomGoodsList(data) {
116
+  if (data === undefined) {
117
+    data = {}
118
+  }
119
+  data['admin_id'] = store.getters.token
120
+  return request({
121
+    url: '/admin/room/goods/list',
122
+    method: 'post',
123
+    data: qs.stringify(data)
124
+  })
125
+}
126
+
127
+export function addRoomGoods(data) {
128
+  if (data === undefined) {
129
+    data = {}
130
+  }
131
+  data['admin_id'] = store.getters.token
132
+  return request({
133
+    url: '/admin/room/goods/add',
134
+    method: 'post',
135
+    data: qs.stringify(data)
136
+  })
137
+}
138
+
139
+export function publishRoomGoods(data) {
140
+  if (data === undefined) {
141
+    data = {}
142
+  }
143
+  data['admin_id'] = store.getters.token
144
+  return request({
145
+    url: '/admin/room/goods/publish',
146
+    method: 'post',
147
+    data: qs.stringify(data)
148
+  })
149
+}
150
+
151
+export function offRoomGoods(data) {
152
+  if (data === undefined) {
153
+    data = {}
154
+  }
155
+  data['admin_id'] = store.getters.token
156
+  return request({
157
+    url: '/admin/room/goods/off',
158
+    method: 'post',
159
+    data: qs.stringify(data)
160
+  })
161
+}
162
+
163
+export function updateRoomGoods(data) {
164
+  if (data === undefined) {
165
+    data = {}
166
+  }
167
+  data['admin_id'] = store.getters.token
168
+  return request({
169
+    url: '/admin/room/goods/update',
170
+    method: 'post',
171
+    data: qs.stringify(data)
172
+  })
173
+}

+ 0 - 0
src/api/uploadFile.js


+ 1 - 0
src/icons/svg/live.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590488890414" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5471" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M866.3 723.2c19.6 0 35.5-15.9 35.5-35.5 0-0.7 0.1-1 0.1-1.4V345.1c0-0.4-0.1-0.7-0.1-1.4 0-19.6-15.9-35.5-35.5-35.5-6 0-11.6 1.5-16.5 4.1h-0.2l-108.3 58.5v-87c0-49.3-39.9-89.2-89.2-89.2h-446c-49.3 0-89.2 39.9-89.2 89.2v446c0 49.3 39.9 89.2 89.2 89.2h446c49.3 0 89.2-39.9 89.2-89.2v-69.3l108.9 58.8c4.9 2.3 10.3 3.9 16.1 3.9z" p-id="5472"></path></svg>

+ 1 - 0
src/icons/svg/order.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590489068967" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7923" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M234.41187483 992.49378741a133.62303423 133.62303423 0 0 1-133.43998896-133.43998897V164.94620156A133.62303423 133.62303423 0 0 1 234.41187483 31.50621259h555.26777297a133.62303423 133.62303423 0 0 1 133.43998897 133.43998897v694.01607427a133.62303423 133.62303423 0 0 1-133.43998897 133.43998895z m0-902.23004882a74.86550821 74.86550821 0 0 0-74.7739856 74.77398558v694.01607427a74.86550821 74.86550821 0 0 0 74.7739856 74.77398558h555.26777297a74.86550821 74.86550821 0 0 0 74.7739856-74.77398558V164.94620156a74.86550821 74.86550821 0 0 0-74.7739856-74.77398558z" p-id="7924"></path><path d="M292.34569718 541.37876299a29.37876299 29.37876299 0 1 1 0-58.66600335h439.30860564a29.37876299 29.37876299 0 1 1 0 58.66600335zM292.34569718 680.12706427a29.37876299 29.37876299 0 1 1 0-58.29991287h299.73660072a29.37876299 29.37876299 0 1 1 0 58.75752601zM292.34569718 402.1728486a29.37876299 29.37876299 0 1 1 0-58.75752601h439.30860564a29.37876299 29.37876299 0 1 1 0 58.75752601z" p-id="7925"></path></svg>

+ 1 - 0
src/icons/svg/warehouse.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590489008972" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7027" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M220.4 96h583.1c42.4 0 78.1 31.9 82.7 74.1l73.2 665.7c2.6 23.5-5 47-20.7 64.6C923 918 900.4 928 876.8 928H147.2c-23.7 0-46.2-10.1-62-27.7-15.8-17.6-23.3-41.1-20.7-64.6L137.7 170c4.7-42.1 40.3-74 82.7-74zM304 345.6c0 114.9 93.1 208 208 208s208-93.1 208-208c-0.1-22.9-18.7-41.4-41.6-41.4-22.9 0-41.5 18.5-41.6 41.4 0 68.9-55.9 124.8-124.8 124.8s-124.8-55.9-124.8-124.8c0.1-14.9-7.8-28.7-20.7-36.2-12.9-7.5-28.8-7.5-41.7 0-13 7.5-20.9 21.3-20.8 36.2z m0 0" p-id="7028"></path></svg>

+ 3 - 0
src/main.js

@@ -12,6 +12,7 @@ import '@/styles/index.scss' // global css
12 12
 import App from './App'
13 13
 import store from './store'
14 14
 import router from './router'
15
+import * as math from 'mathjs'
15 16
 
16 17
 import './icons' // icon
17 18
 import './permission' // permission control
@@ -41,6 +42,8 @@ Object.keys(filters).forEach(key => {
41 42
   Vue.filter(key, filters[key])
42 43
 })
43 44
 
45
+Vue.prototype.$math = math
46
+
44 47
 Vue.config.productionTip = false
45 48
 
46 49
 new Vue({

+ 35 - 4
src/router/index.js

@@ -85,15 +85,46 @@ export const constantRoutes = [
85 85
  * the routes that need to be dynamically loaded based on user roles
86 86
  */
87 87
 export const asyncRoutes = [
88
+  // {
89
+  //   path: '/order',
90
+  //   component: Layout,
91
+  //   children: [
92
+  //     {
93
+  //       path: '',
94
+  //       component: () => import('@/views/order/index'),
95
+  //       name: 'Order',
96
+  //       meta: { title: '订单详情', icon: 'icon', noCache: true }
97
+  //     }
98
+  //   ]
99
+  // },
88 100
   {
89
-    path: '/order',
101
+    path: '/live',
90 102
     component: Layout,
103
+    meta: { title: '直播', icon: 'live', noCache: true },
91 104
     children: [
92 105
       {
93
-        path: '',
94
-        component: () => import('@/views/order/index'),
106
+        path: 'room',
107
+        component: () => import('@/views/live/room'),
108
+        name: 'Room',
109
+        meta: { title: '直播间列表', icon: 'table', noCache: true }
110
+      },
111
+      {
112
+        path: 'order',
113
+        component: () => import('@/views/live/order'),
95 114
         name: 'Order',
96
-        meta: { title: '订单详情', icon: 'icon', noCache: true }
115
+        meta: { title: '订单', icon: 'order', noCache: true }
116
+      },
117
+      {
118
+        path: 'goods',
119
+        component: () => import('@/views/live/goods'),
120
+        name: 'Goods',
121
+        meta: { title: '商品库', icon: 'warehouse', noCache: true }
122
+      },
123
+      {
124
+        path: 'roomGoods',
125
+        component: () => import('@/views/live/roomGoods'),
126
+        name: 'roomGoods',
127
+        meta: { title: '直播间商品库', icon: 'warehouse', noCache: true }
97 128
       }
98 129
     ]
99 130
   },

+ 2 - 2
src/utils/request.js

@@ -1,11 +1,11 @@
1 1
 import axios from 'axios'
2 2
 import { MessageBox, Message } from 'element-ui'
3 3
 import store from '@/store'
4
-import { getToken } from '@/utils/auth'
4
+// import { getToken } from '@/utils/auth'
5 5
 
6 6
 // create an axios instance
7 7
 const service = axios.create({
8
-  baseURL: 'http://kodo.xfoto.com.cn/api', // url = base url + request url
8
+  baseURL: 'http://jh.kodo.com.cn/api', // url = base url + request url
9 9
   // withCredentials: true, // send cookies when cross-domain requests
10 10
   timeout: 5000 // request timeout
11 11
 })

+ 386 - 0
src/views/live/goods.vue

@@ -0,0 +1,386 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-button v-waves class="filter-item" type="primary" icon="el-icon-circle-plus-outline" @click="handleCreate">
5
+        新增
6
+      </el-button>
7
+      <el-button v-waves :loading="refreshNetworkLoading" class="filter-item" type="primary" icon="el-icon-refresh" @click="handleRefreshAudit">
8
+        刷新审核状态
9
+      </el-button>
10
+      <el-checkbox v-model="showGoodsID" class="filter-item" style="margin-left:15px;">
11
+        商品ID
12
+      </el-checkbox>
13
+      <el-checkbox v-model="showWXGoodsID" class="filter-item" style="margin-left:15px;">
14
+        商品微信ID
15
+      </el-checkbox>
16
+    </div>
17
+
18
+    <el-table
19
+      id="goods-table"
20
+      v-loading="listLoading"
21
+      :data="list"
22
+      border
23
+      fit
24
+      highlight-current-row
25
+      style="width: 100%;"
26
+    >
27
+      <el-table-column v-if="showGoodsID" label="商品ID" prop="id" align="center" width="80">
28
+        <template slot-scope="{row}">
29
+          <span>{{ row.goods_id }}</span>
30
+        </template>
31
+      </el-table-column>
32
+      <el-table-column v-if="showWXGoodsID" label="微信商品ID" prop="id" align="center" width="80">
33
+        <template slot-scope="{row}">
34
+          <span>{{ row.wx_goods_id }}</span>
35
+        </template>
36
+      </el-table-column>
37
+      <el-table-column label="商品图片" align="center" width="130px">
38
+        <template slot-scope="{row}">
39
+          <el-image
40
+            style="width: 100px; height: 100px"
41
+            :src="row.goods_img"
42
+            fit="contain"
43
+          />
44
+        </template>
45
+      </el-table-column>
46
+      <el-table-column label="商品名称" align="center">
47
+        <template slot-scope="{row}">
48
+          <span>{{ row.name }}</span>
49
+        </template>
50
+      </el-table-column>
51
+      <el-table-column label="价格" align="center" width="150px">
52
+        <template slot-scope="{row}">
53
+          <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
54
+          <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
55
+        </template>
56
+      </el-table-column>
57
+      <el-table-column label="审核状态" align="center" width="150px">
58
+        <template slot-scope="{row}">
59
+          <el-tag :type="row.audit_status | statusFilter">
60
+            {{ statusOptions[row.audit_status] }}
61
+          </el-tag>
62
+        </template>
63
+      </el-table-column>
64
+      <el-table-column label="动作" align="center" class-name="small-padding fixed-width" fixed="right">
65
+        <template slot-scope="{row,$index}">
66
+          <el-button type="danger" size="mini" @click="handleDelete(row, $index)">
67
+            删除
68
+          </el-button>
69
+          <el-button v-if="row.audit_status === 2" type="primary" size="mini" @click="handleUpdate(row, $index)">
70
+            更新
71
+          </el-button>
72
+        </template>
73
+      </el-table-column>
74
+    </el-table>
75
+
76
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
77
+
78
+    <el-dialog :visible.sync="dialogFormVisible" width="700px">
79
+      <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="80px" style="width: 550px; margin-left:50px;">
80
+        <el-form-item label="商品名称" prop="goods_name">
81
+          <el-row>
82
+            <el-input
83
+              v-model="temp.goods_name"
84
+              placeholder="请输入商品名"
85
+              :disabled="dialogStatus === 'update'"
86
+              maxlength="28"
87
+              show-word-limit
88
+              style="width: 450px"
89
+            />
90
+          </el-row>
91
+        </el-form-item>
92
+        <el-form-item label="商品价格" prop="price">
93
+          <el-row>
94
+            <el-col :span="6">
95
+              <el-radio v-model="temp.price_type" :label="1">一口价</el-radio>
96
+            </el-col>
97
+            <el-col :span="8">
98
+              <span>价格</span>
99
+              <el-input v-model="temp.price1" :disabled="temp.price_type !== 1" style="width:100px">
100
+                <span slot="suffix">元</span>
101
+              </el-input>
102
+            </el-col>
103
+          </el-row>
104
+          <el-row style="margin-top: 12px">
105
+            <el-col :span="6">
106
+              <el-radio v-model="temp.price_type" :label="3">显示折扣价</el-radio>
107
+            </el-col>
108
+            <el-col :span="9">
109
+              <span>原价</span>
110
+              <el-input v-model="temp.price2" :disabled="temp.price_type !== 3" prop="price2" style="width:100px">
111
+                <span slot="suffix">元</span>
112
+              </el-input>
113
+            </el-col>
114
+            <el-col :span="9">
115
+              <span>折扣价</span>
116
+              <el-input v-model="temp.price3" :disabled="temp.price_type !== 3" prop="price3" style="width:100px">
117
+                <span slot="suffix">元</span>
118
+              </el-input>
119
+            </el-col>
120
+          </el-row>
121
+        </el-form-item>
122
+        <el-form-item label="商品封面" prop="goods_img">
123
+          <el-image
124
+            v-if="dialogStatus === 'update'"
125
+            style="width: 150px; height: 150px"
126
+            :src="temp.goods_img"
127
+            fit="contain"
128
+          />
129
+          <el-upload
130
+            v-else
131
+            drag
132
+            :multiple="false"
133
+            :limit="1"
134
+            action="https://jh.kodo.com.cn/api/upload"
135
+            :on-success="handleUploadSuccess"
136
+            :file-list="temp.imgList"
137
+            list-type="picture"
138
+            style="width: 450px"
139
+          >
140
+            <i class="el-icon-upload" />
141
+            <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
142
+            <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
143
+          </el-upload>
144
+        </el-form-item>
145
+      </el-form>
146
+      <div slot="footer" class="dialog-footer">
147
+        <el-button @click="dialogFormVisible = false">
148
+          取消
149
+        </el-button>
150
+        <el-button v-waves :loading="submitNetworkLoading" type="primary" @click="dialogStatus==='create'?createData():updateData()">
151
+          提交审核
152
+        </el-button>
153
+      </div>
154
+    </el-dialog>
155
+  </div>
156
+</template>
157
+
158
+<script>
159
+import { fetchGoodsList, createGoods, auditGoods, deleteGoods, updateGoods } from '@/api/live'
160
+import waves from '@/directive/waves' // waves directive
161
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
162
+
163
+export default {
164
+  name: 'ComplexTable',
165
+  components: { Pagination },
166
+  directives: { waves },
167
+  filters: {
168
+    statusFilter(status) {
169
+      const statusMap = {
170
+        0: 'info',
171
+        1: '',
172
+        2: 'success',
173
+        3: 'danger'
174
+      }
175
+      return statusMap[status]
176
+    }
177
+  },
178
+  data() {
179
+    var validatePrice = (rule, value, callback) => {
180
+      if (this.temp.price_type === 1) {
181
+        if (this.temp.price1 === '') {
182
+          callback(new Error('价格不能为空'))
183
+        } else {
184
+          callback()
185
+        }
186
+      } else {
187
+        if (this.temp.price2 === '') {
188
+          callback(new Error('原价不能为空'))
189
+        } else if (this.temp.price3 === '') {
190
+          callback(new Error('折扣价不能为空'))
191
+        } else if (parseFloat(this.temp.price2) <= parseFloat(this.temp.price3)) {
192
+          callback(new Error('折扣价不能大于原价'))
193
+        }
194
+      }
195
+    }
196
+    return {
197
+      list: null,
198
+      total: 0,
199
+      listLoading: true,
200
+      listQuery: {
201
+        page: 1,
202
+        num: 20
203
+      },
204
+      temp: {
205
+        goods_name: '',
206
+        price_type: 1,
207
+        price: '',
208
+        price1: '',
209
+        price2: '',
210
+        price3: '',
211
+        goods_img: '',
212
+        imgList: []
213
+      },
214
+      statusOptions: ['未审核', '审核中', '审核通过', '审核失败'],
215
+      dialogFormVisible: false,
216
+      dialogStatus: '',
217
+      rules: {
218
+        goods_name: [{ required: true, message: 'title is required', trigger: 'blur' }],
219
+        price: [{ validator: validatePrice, trigger: 'blur' }],
220
+        goods_img: [{ required: true, message: 'title is required', trigger: 'changed' }]
221
+      },
222
+      submitNetworkLoading: false,
223
+      refreshNetworkLoading: false,
224
+      showGoodsID: false,
225
+      showWXGoodsID: false
226
+    }
227
+  },
228
+  created() {
229
+    this.getList()
230
+  },
231
+  methods: {
232
+    getList() {
233
+      this.listLoading = true
234
+      var _self = this
235
+      fetchGoodsList(this.listQuery).then(response => {
236
+        _self.list = response.data.goods_list
237
+        _self.total = response.data.count
238
+        // Just to simulate the time of the request
239
+        this.listLoading = false
240
+        this.refreshNetworkLoading = false
241
+        this.submitNetworkLoading = false
242
+      })
243
+    },
244
+
245
+    resetTemp() {
246
+      this.temp = {
247
+        goods_name: '',
248
+        price_type: 1,
249
+        price: '',
250
+        price1: '',
251
+        price2: '',
252
+        price3: '',
253
+        goods_img: '',
254
+        imgList: []
255
+      }
256
+    },
257
+
258
+    handleUploadChanged(file, fileList) {
259
+      this.temp.imgList = [{ name: file.name, url: file.url }]
260
+    },
261
+
262
+    handleUploadSuccess(response, file, fileList) {
263
+      this.temp.goods_img = response.data.file_path
264
+    },
265
+
266
+    handleFilter() {
267
+      this.getList()
268
+    },
269
+
270
+    handleCreate() {
271
+      this.resetTemp()
272
+      this.dialogFormVisible = true
273
+      this.dialogStatus = 'create'
274
+    },
275
+
276
+    createData() {
277
+      var _self = this
278
+      this.$refs['dataForm'].validate((valid) => {
279
+        if (valid) {
280
+          // this.submitNetworkLoading = true
281
+          const goods = Object.assign({}, this.temp)
282
+          if (goods.price_type === 1) {
283
+            goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price1)), this.$math.bignumber(100)).d[0]
284
+            goods.price2 = 0
285
+          } else if (goods.price_type === 3) {
286
+            goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price2)), this.$math.bignumber(100)).d[0]
287
+            goods.price2 = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price3)), this.$math.bignumber(100)).d[0]
288
+          }
289
+
290
+          createGoods(goods).then(response => {
291
+            _self.getList()
292
+            _self.resetTemp()
293
+            _self.dialogFormVisible = false
294
+
295
+            _self.$notify({
296
+              title: '创建商品成功',
297
+              type: 'success',
298
+              duration: 2000
299
+            })
300
+          })
301
+        }
302
+      })
303
+    },
304
+
305
+    handleDelete(row, index) {
306
+      var _self = this
307
+      this.$confirm(`确定要删除 ${row.name}`, '', {
308
+        distinguishCancelAndClose: true,
309
+        confirmButtonText: '删除',
310
+        cancelButtonText: '取消',
311
+        type: 'error'
312
+      })
313
+        .then(() => {
314
+          deleteGoods(row).then(response => {
315
+            _self.$notify({
316
+              title: '删除商品成功',
317
+              type: 'success',
318
+              duration: 2000
319
+            })
320
+          })
321
+        })
322
+        .catch(action => {
323
+
324
+        })
325
+    },
326
+
327
+    handleRefreshAudit() {
328
+      this.refreshNetworkLoading = true
329
+      var _self = this
330
+      auditGoods().then(response => {
331
+        _self.getList()
332
+        _self.$notify({
333
+          title: '刷新审核状态成功',
334
+          type: 'success',
335
+          duration: 2000
336
+        })
337
+      })
338
+    },
339
+
340
+    handleUpdate(row, index) {
341
+      this.resetTemp()
342
+      this.dialogFormVisible = true
343
+      this.dialogStatus = 'update'
344
+      const goods = Object.assign({}, row)
345
+      this.temp.goods_id = goods.goods_id
346
+      this.temp.goods_name = goods.name
347
+      this.temp.goods_img = goods.goods_img
348
+      this.temp.price_type = goods.price_type
349
+      if (this.temp.price_type === 1) {
350
+        this.temp.price1 = `${parseInt(goods.price) / 100}`
351
+        this.temp.price2 = ''
352
+        this.temp.price3 = ''
353
+      } else {
354
+        this.temp.price1 = ''
355
+        this.temp.price3 = `${parseInt(goods.price2) / 100}`
356
+        this.temp.price2 = `${parseInt(goods.price) / 100}`
357
+      }
358
+    },
359
+
360
+    updateData() {
361
+      this.submitNetworkLoading = true
362
+      var _self = this
363
+
364
+      const goods = Object.assign({}, this.temp)
365
+      if (goods.price_type === 1) {
366
+        goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price1)), this.$math.bignumber(100)).d[0]
367
+        goods.price2 = 0
368
+      } else if (goods.price_type === 3) {
369
+        goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price2)), this.$math.bignumber(100)).d[0]
370
+        goods.price2 = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price3)), this.$math.bignumber(100)).d[0]
371
+      }
372
+      updateGoods(goods).then(response => {
373
+        _self.getList()
374
+        this.resetTemp()
375
+        this.dialogFormVisible = false
376
+        this.dialogStatus = ''
377
+        _self.$notify({
378
+          title: '更新成功',
379
+          type: 'success',
380
+          duration: 2000
381
+        })
382
+      })
383
+    }
384
+  }
385
+}
386
+</script>

+ 177 - 0
src/views/live/order.vue

@@ -0,0 +1,177 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-input v-model="listQuery.query" placeholder="顾客名字,顾客电话" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
5
+      <el-select v-model="listQuery.pay_status" placeholder="支付状态" clearable class="filter-item" style="width: 130px">
6
+        <el-option v-for="(item, index) in statusOptions" :key="item" :value="index" :label="item" />
7
+      </el-select>
8
+      <el-button v-waves :loading="searchNetworkLoading" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
9
+        搜索
10
+      </el-button>
11
+      <el-checkbox v-model="showOrderID" class="filter-item" style="margin-left:15px;">
12
+        订单ID
13
+      </el-checkbox>
14
+      <el-checkbox v-model="showTransactionID" class="filter-item" style="margin-left:15px;">
15
+        商户号交易单号
16
+      </el-checkbox>
17
+    </div>
18
+
19
+    <el-table
20
+      id="order-table"
21
+      v-loading="listLoading"
22
+      :data="list"
23
+      border
24
+      fit
25
+      highlight-current-row
26
+      style="width: 100%;"
27
+    >
28
+      <el-table-column v-if="showOrderID" label="订单ID" prop="id" align="center">
29
+        <template slot-scope="{row}">
30
+          <span>{{ row.order_id }}</span>
31
+        </template>
32
+      </el-table-column>
33
+      <el-table-column v-if="showTransactionID" label="商户号交易单号" align="center">
34
+        <template slot-scope="{row}">
35
+          <span>{{ row.transaction_id }}</span>
36
+        </template>
37
+      </el-table-column>
38
+      <el-table-column label="商品" align="center" width="110px">
39
+        <template slot-scope="{row}">
40
+          <el-image
41
+            style="width: 80px; height: 80px"
42
+            :src="row.goods_img"
43
+            fit="contain"
44
+          />
45
+        </template>
46
+      </el-table-column>
47
+      <el-table-column label="商品名称" align="center">
48
+        <template slot-scope="{row}">
49
+          <span>{{ row.goods_name }}</span>
50
+          <span style="color: #409EFF">x {{ row.amount }}</span>
51
+        </template>
52
+      </el-table-column>
53
+      <el-table-column label="总金额" align="center">
54
+        <template slot-scope="{row}">
55
+          <span>{{ row.total_fee / 100 }}元</span>
56
+        </template>
57
+      </el-table-column>
58
+      <el-table-column label="顾客名称" align="center">
59
+        <template slot-scope="{row}">
60
+          <span>{{ row.name }}</span>
61
+        </template>
62
+      </el-table-column>
63
+      <el-table-column label="顾客电话" align="center">
64
+        <template slot-scope="{row}">
65
+          <span>{{ row.phone }}</span>
66
+        </template>
67
+      </el-table-column>
68
+      <el-table-column label="顾客地址" align="center">
69
+        <template slot-scope="{row}">
70
+          <span>{{ row.province + row.city + row.county + row.address }}</span>
71
+        </template>
72
+      </el-table-column>
73
+      <el-table-column label="直播主题" align="center">
74
+        <template slot-scope="{row}">
75
+          <span>{{ row.room_name }}</span>
76
+        </template>
77
+      </el-table-column>
78
+      <el-table-column label="快递单号" align="center">
79
+        <template slot-scope="{row}">
80
+          <span>{{ row.tracking_number }}</span>
81
+        </template>
82
+      </el-table-column>
83
+      <el-table-column label="支付状态" align="center" width="150px">
84
+        <template slot-scope="{row}">
85
+          <el-tag :type="row.pay_status | statusFilter">
86
+            {{ statusOptions[row.pay_status] }}
87
+          </el-tag>
88
+        </template>
89
+      </el-table-column>
90
+      <el-table-column label="时间" align="center" width="150px">
91
+        <template slot-scope="{row}">
92
+          <span>{{ row.paid_at }}</span>
93
+        </template>
94
+      </el-table-column>
95
+      <el-table-column label="Actions" align="center" class-name="small-padding fixed-width" fixed="right" width="100">
96
+        <template slot-scope="{row,$index}">
97
+          <el-button v-if="(row.tracking_number === null || row.tracking_number === '') && row.pay_status === 1" type="primary" @click="handleDelivery(row, $index)">发货</el-button>
98
+          <el-button v-else-if="row.tracking_number !== null && row.pay_status === 1" type="success" disabled>已发货</el-button>
99
+          <el-button v-else type="info" disabled>发货</el-button>
100
+        </template>
101
+      </el-table-column>
102
+    </el-table>
103
+
104
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
105
+  </div>
106
+</template>
107
+
108
+<script>
109
+import { fetchOrderList, deliveryOrder } from '@/api/live'
110
+import waves from '@/directive/waves' // waves directive
111
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
112
+
113
+export default {
114
+  name: 'ComplexTable',
115
+  components: { Pagination },
116
+  directives: { waves },
117
+  filters: {
118
+    statusFilter(status) {
119
+      const statusMap = {
120
+        1: 'success',
121
+        0: 'warn',
122
+        2: 'danger'
123
+      }
124
+      return statusMap[status]
125
+    }
126
+  },
127
+  data() {
128
+    return {
129
+      tableKey: 0,
130
+      list: null,
131
+      total: 0,
132
+      listLoading: true,
133
+      searchNetworkLoading: false,
134
+      statusOptions: ['支付中', '已支付', '支付失败'],
135
+      showOrderID: false,
136
+      showTransactionID: false,
137
+
138
+      listQuery: {
139
+        page: 1,
140
+        num: 20,
141
+        pay_status: '',
142
+        query: ''
143
+      }
144
+    }
145
+  },
146
+  created() {
147
+    this.getList()
148
+  },
149
+  methods: {
150
+    getList(query) {
151
+      this.listLoading = true
152
+      var _self = this
153
+      fetchOrderList(this.listQuery).then(response => {
154
+        _self.list = response.data.orders
155
+        _self.total = response.data.count
156
+        // Just to simulate the time of the request
157
+        _self.listLoading = false
158
+        _self.searchNetworkLoading = false
159
+      })
160
+    },
161
+
162
+    handleFilter() {
163
+      this.searchNetworkLoading = true
164
+      this.getList(this.listQuery.title)
165
+    },
166
+
167
+    handleDelivery(row, index) {
168
+      this.listLoading = true
169
+      var _self = this
170
+      deliveryOrder(row).then(response => {
171
+        _self.$set(_self.list, index, response.data.order)
172
+        _self.listLoading = false
173
+      })
174
+    }
175
+  }
176
+}
177
+</script>

+ 362 - 0
src/views/live/room.vue

@@ -0,0 +1,362 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-input v-model="listQuery.query" placeholder="搜索直播主题" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
5
+      <el-select v-model="listQuery.live_status" placeholder="直播状态" clearable class="filter-item" style="width: 130px">
6
+        <el-option v-for="(k, v) in statusOptions" :key="k" :value="v" :label="k" />
7
+      </el-select>
8
+      <el-button v-waves :loading="networkLoading" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
9
+        搜索
10
+      </el-button>
11
+      <el-button v-waves :loading="networkLoading" class="filter-item" type="primary" icon="el-icon-refresh" @click="handleRefresh">
12
+        从微信获取直播列表
13
+      </el-button>
14
+    </div>
15
+
16
+    <el-table
17
+      id="room-table"
18
+      :key="tableKey"
19
+      ref="multipleTable"
20
+      v-loading="listLoading"
21
+      :data="list"
22
+      border
23
+      fit
24
+      highlight-current-row
25
+      style="width: 100%;"
26
+    >
27
+      <el-table-column label="room_id" prop="房间号" align="center" width="80">
28
+        <template slot-scope="{row}">
29
+          <span>{{ row.room_id }}</span>
30
+        </template>
31
+      </el-table-column>
32
+      <el-table-column label="直播主题" align="center">
33
+        <template slot-scope="{row}">
34
+          <span>{{ row.name }}</span>
35
+        </template>
36
+      </el-table-column>
37
+      <el-table-column label="主播" align="center">
38
+        <template slot-scope="{row}">
39
+          <el-avatar shape="square" :src="row.anchor_avatar" />
40
+          <span>{{ row.anchor_name }}</span>
41
+        </template>
42
+      </el-table-column>
43
+      <el-table-column label="直播状态" align="center">
44
+        <template slot-scope="{row}">
45
+          <el-tag :type="row.live_status | statusFilter">
46
+            {{ statusOptions[row.live_status] }}
47
+          </el-tag>
48
+        </template>
49
+      </el-table-column>
50
+      <el-table-column label="直播封面" align="center">
51
+        <template slot-scope="{row}">
52
+          <el-image
53
+            style="width: 100px; height: 100px"
54
+            :src="row.cover_img"
55
+            fit="contain"
56
+          />
57
+        </template>
58
+      </el-table-column>
59
+      <el-table-column label="直播分享卡片" align="center">
60
+        <template slot-scope="{row}">
61
+          <el-image
62
+            style="width: 200px; height: 160px"
63
+            :src="row.share_img"
64
+            fit="contain"
65
+          />
66
+        </template>
67
+      </el-table-column>
68
+      <el-table-column label="Actions" align="center" class-name="small-padding fixed-width" fixed="right">
69
+        <template slot-scope="{row}">
70
+          <el-button v-if="row.live_status == 102 || row.live_status == 101" type="primary" @click="handleAddGoods(row)">添加商品</el-button>
71
+          <el-button v-else type="info" disabled>添加商品</el-button>
72
+        </template>
73
+      </el-table-column>
74
+    </el-table>
75
+
76
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
77
+
78
+    <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible">
79
+      <el-table
80
+        id="room-table"
81
+        v-loading="goodsListLoading"
82
+        :data="goodsList"
83
+        fit
84
+        highlight-current-row
85
+        height="400px"
86
+        style="width: 100%;"
87
+        @selection-change="handleSelectionChange"
88
+      >
89
+        <el-table-column
90
+          type="selection"
91
+          width="30"
92
+        />
93
+        <el-table-column label="商品图片" align="center">
94
+          <template slot-scope="{row}">
95
+            <el-image
96
+              style="width: 60px; height: 60px"
97
+              :src="row.goods_img"
98
+              fit="contain"
99
+            />
100
+          </template>
101
+        </el-table-column>
102
+        <el-table-column label="商品名称" align="center">
103
+          <template slot-scope="{row}">
104
+            <span>{{ row.name }}</span>
105
+          </template>
106
+        </el-table-column>
107
+        <el-table-column label="价格" align="center" width="150px">
108
+          <template slot-scope="{row}">
109
+            <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
110
+            <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
111
+          </template>
112
+        </el-table-column>
113
+        <pagination v-show="goodsTotal>0" :total="goodsTotal" :page.sync="goodsListQuery.page" :limit.sync="goodsListQuery.num" @pagination="getGoodsList" />
114
+      </el-table>
115
+      <div slot="footer" class="dialog-footer">
116
+        <el-button @click="handleUnaddGoods">
117
+          取消
118
+        </el-button>
119
+        <el-button :disabled="temp.goods_list.length === 0" type="primary" @click="handleAddGoodsNextStep()">
120
+          下一步
121
+        </el-button>
122
+      </div>
123
+    </el-dialog>
124
+    <el-dialog :title="dialogTitle" :visible.sync="dialogForAddGoodsFormVisible">
125
+      <el-table
126
+        id="room-table"
127
+        :data="temp.goods_list"
128
+        fit
129
+        highlight-current-row
130
+        height="300px"
131
+        style="width: 100%;"
132
+        @selection-change="handleSelectionChange"
133
+      >
134
+        <el-table-column label="商品图片" align="center">
135
+          <template slot-scope="{row}">
136
+            <el-image
137
+              style="width: 60px; height: 60px"
138
+              :src="row.goods_img"
139
+              fit="contain"
140
+            />
141
+          </template>
142
+        </el-table-column>
143
+        <el-table-column label="商品名称" align="center">
144
+          <template slot-scope="{row}">
145
+            <span>{{ row.name }}</span>
146
+          </template>
147
+        </el-table-column>
148
+        <el-table-column label="价格" align="center" width="150px">
149
+          <template slot-scope="{row}">
150
+            <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
151
+            <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
152
+          </template>
153
+        </el-table-column>
154
+        <el-table-column label="库存" align="center" width="150px">
155
+          <template slot-scope="{row}">
156
+            <el-input-number v-model="row.inventory" :min="1" size="small" label="描述文字" @change="handleInventoryChanged" />
157
+          </template>
158
+        </el-table-column>
159
+        <pagination :total="temp.goods_list.length" />
160
+      </el-table>
161
+      <div slot="footer" class="dialog-footer">
162
+        <el-button @click="handleUnaddGoods">
163
+          取消
164
+        </el-button>
165
+        <el-button type="primary" @click="handleAddGoodsPrevStep">
166
+          上一步
167
+        </el-button>
168
+        <el-button v-waves :loading="networkLoading" :disabled="addGoodsEnable" type="primary" @click="handleAddGoodsToRoom()">
169
+          添加
170
+        </el-button>
171
+      </div>
172
+    </el-dialog>
173
+  </div>
174
+</template>
175
+
176
+<script>
177
+import { addRoomGoods, fetchGoodsList, fetchRoomList, refreshWxRoomList } from '@/api/live'
178
+import waves from '@/directive/waves' // waves directive
179
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
180
+
181
+export default {
182
+  name: 'ComplexTable',
183
+  components: { Pagination },
184
+  directives: { waves },
185
+  filters: {
186
+    statusFilter(status) {
187
+      const statusMap = {
188
+        101: '',
189
+        102: 'success',
190
+        103: 'info',
191
+        104: 'danger',
192
+        105: 'danger',
193
+        106: 'danger',
194
+        107: 'warning'
195
+
196
+      }
197
+      return statusMap[status]
198
+    }
199
+  },
200
+  data() {
201
+    return {
202
+      tableKey: 0,
203
+      list: null,
204
+      total: 0,
205
+      listLoading: true,
206
+      listQuery: {
207
+        page: 1,
208
+        num: 20,
209
+        query: '',
210
+        live_status: ''
211
+      },
212
+
213
+      statusOptions: {
214
+        101: '直播中',
215
+        102: '未开始',
216
+        103: '已结束',
217
+        104: '禁播',
218
+        105: '暂停中',
219
+        106: '异常',
220
+        107: '已过期'
221
+      },
222
+      networkLoading: false,
223
+      dialogFormVisible: false,
224
+      dialogTitle: '',
225
+
226
+      goodsList: null,
227
+      goodsTotal: 0,
228
+      goodsListLoading: true,
229
+      goodsListQuery: {
230
+        page: 1,
231
+        num: 20,
232
+        room_id: ''
233
+      },
234
+
235
+      temp: {
236
+        room_id: '',
237
+        anchor_id: '',
238
+        goods_list: []
239
+      },
240
+      dialogForAddGoodsFormVisible: false,
241
+      addGoodsEnable: false
242
+    }
243
+  },
244
+  created() {
245
+    this.getList()
246
+  },
247
+  methods: {
248
+    getList() {
249
+      this.listLoading = true
250
+      var _self = this
251
+      fetchRoomList(this.listQuery).then(response => {
252
+        _self.list = response.data.rooms
253
+        _self.total = response.data.count
254
+        // Just to simulate the time of the request
255
+        _self.listLoading = false
256
+        _self.networkLoading = false
257
+      })
258
+    },
259
+
260
+    getGoodsList(room_id) {
261
+      this.goodsListLoading = true
262
+      var _self = this
263
+      this.goodsListQuery.room_id = room_id
264
+      fetchGoodsList(this.goodsListQuery).then(response => {
265
+        _self.goodsList = response.data.goods_list
266
+        _self.goodsTotal = response.data.count
267
+        // Just to simulate the time of the request
268
+        this.goodsListLoading = false
269
+      })
270
+    },
271
+
272
+    resetTemp() {
273
+      this.goodsList = null
274
+      this.goodsTotal = 0
275
+      this.goodsListQuery = {
276
+        page: 1,
277
+        num: 20,
278
+        room_id: ''
279
+      }
280
+
281
+      this.temp = {
282
+        room_id: '',
283
+        anchor_id: '',
284
+        goods_list: []
285
+      }
286
+    },
287
+
288
+    handleFilter() {
289
+      this.getList()
290
+    },
291
+
292
+    handleRefresh() {
293
+      this.listLoading = true
294
+      this.networkLoading = true
295
+      var _self = this
296
+      refreshWxRoomList().then(response => {
297
+        fetchRoomList().then(response => {
298
+          _self.list = response.data.rooms
299
+          _self.total = response.data.count
300
+          // Just to simulate the time of the request
301
+          this.listLoading = false
302
+          _self.networkLoading = false
303
+        })
304
+      })
305
+    },
306
+
307
+    handleAddGoods(row) {
308
+      this.dialogFormVisible = true
309
+      this.dialogTitle = row.name
310
+      this.temp.room_id = row.room_id
311
+      this.temp.anchor_id = row.anchor_id
312
+      this.getGoodsList(row.room_id)
313
+    },
314
+
315
+    handleSelectionChange(v) {
316
+      this.temp.goods_list = v
317
+      this.$set(this.temp, 'goods_list', v)
318
+    },
319
+
320
+    handleUnaddGoods() {
321
+      this.dialogForAddGoodsFormVisible = false
322
+      this.dialogFormVisible = false
323
+      this.resetTemp()
324
+    },
325
+
326
+    handleAddGoodsNextStep() {
327
+      this.dialogForAddGoodsFormVisible = true
328
+      console.log(this.temp)
329
+      this.temp.goods_list = this.temp.goods_list.map(goods => {
330
+        goods.inventory = ''
331
+        return goods
332
+      })
333
+    },
334
+
335
+    handleInventoryChanged(v) {
336
+      this.temp.goods_list.filter(v => {
337
+        return v.inventory !== ''
338
+      })
339
+    },
340
+
341
+    handleAddGoodsPrevStep() {
342
+      this.dialogForAddGoodsFormVisible = false
343
+    },
344
+
345
+    handleAddGoodsToRoom() {
346
+      var _self = this
347
+      this.networkLoading = true
348
+      const params = Object.assign({}, this.temp)
349
+      params.goods_list = JSON.stringify(this.temp.goods_list)
350
+      addRoomGoods(params).then(response => {
351
+        console.log(response)
352
+        if (response.status === 200) {
353
+          _self.dialogForAddGoodsFormVisible = false
354
+          _self.dialogFormVisible = false
355
+          _self.networkLoading = false
356
+          _self.resetTemp()
357
+        }
358
+      })
359
+    }
360
+  }
361
+}
362
+</script>

+ 216 - 0
src/views/live/roomGoods.vue

@@ -0,0 +1,216 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-checkbox v-model="showGoodsID" class="filter-item" style="margin-left:15px;">
5
+        商品ID
6
+      </el-checkbox>
7
+      <el-checkbox v-model="showWXGoodsID" class="filter-item" style="margin-left:15px;">
8
+        微信商品ID
9
+      </el-checkbox>
10
+      <el-checkbox v-model="showRoomID" class="filter-item" style="margin-left:15px;">
11
+        直播间ID
12
+      </el-checkbox>
13
+    </div>
14
+
15
+    <el-table
16
+      id="goods-table"
17
+      v-loading="listLoading"
18
+      :data="list"
19
+      border
20
+      fit
21
+      highlight-current-row
22
+      style="width: 100%;"
23
+    >
24
+      <el-table-column v-if="showRoomID" label="房间ID" prop="id" align="center">
25
+        <template slot-scope="{row}">
26
+          <span>{{ row.room_id }}</span>
27
+        </template>
28
+      </el-table-column>
29
+      <el-table-column label="直播主题" prop="id" align="center">
30
+        <template slot-scope="{row}">
31
+          <span>{{ row.room_name }}</span>
32
+        </template>
33
+      </el-table-column>
34
+      <el-table-column label="主播" prop="id" align="center">
35
+        <template slot-scope="{row}">
36
+          <span>{{ row.anchor_name }}</span>
37
+        </template>
38
+      </el-table-column>
39
+      <el-table-column v-if="showGoodsID" label="商品ID" prop="id" align="center">
40
+        <template slot-scope="{row}">
41
+          <span>{{ row.goods_id }}</span>
42
+        </template>
43
+      </el-table-column>
44
+      <el-table-column v-if="showWXGoodsID" label="微信商品ID" prop="id" align="center">
45
+        <template slot-scope="{row}">
46
+          <span>{{ row.wx_goods_id }}</span>
47
+        </template>
48
+      </el-table-column>
49
+      <el-table-column label="商品名称" align="center">
50
+        <template slot-scope="{row}">
51
+          <span>{{ row.goods_name }}</span>
52
+        </template>
53
+      </el-table-column>
54
+      <el-table-column label="商品图片" align="center" width="120px">
55
+        <template slot-scope="{row}">
56
+          <el-image
57
+            style="width: 90px; height: 90px"
58
+            :src="row.goods_img"
59
+            fit="contain"
60
+          />
61
+        </template>
62
+      </el-table-column>
63
+      <el-table-column label="价格" align="center" width="150px">
64
+        <template slot-scope="{row}">
65
+          <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
66
+          <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
67
+        </template>
68
+      </el-table-column>
69
+      <el-table-column label="商品状态" align="center">
70
+        <template slot-scope="{row}">
71
+          <el-tag :type="row.goods_status | statusFilter">{{ statusOptions[row.goods_status] }}</el-tag>
72
+        </template>
73
+      </el-table-column>
74
+      <el-table-column label="库存" align="center" width="200px">
75
+        <template slot-scope="{row}">
76
+          <div v-if="!row.isEditable">
77
+            <span v-if="row.inventory > 0">{{ row.inventory }}</span>
78
+            <el-tag v-else type="danger">库存不足</el-tag>
79
+          </div>
80
+          <div v-if="row.isEditable">
81
+            <el-input v-model="inventory" style="width:50px;" @keyup.enter.native="handleInventoryChanged(row)" />
82
+            <el-button type="info" size="mini" @click="handleUpdateCancel(row)">取消</el-button>
83
+          </div>
84
+        </template>
85
+      </el-table-column>
86
+      <el-table-column label="销售数量" align="center">
87
+        <template slot-scope="{row}">
88
+          <span>{{ row.sale_count }}</span>
89
+        </template>
90
+      </el-table-column>
91
+      <el-table-column label="动作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
92
+        <template slot-scope="{row}">
93
+          <el-button v-if="(row.goods_status === 1 || row.goods_status === 2) && (row.room_status == 102 || row.room_status == 101)" type="success" size="mini" @click="handlePublish(row)">
94
+            上架
95
+          </el-button>
96
+          <el-button v-else-if="(row.goods_status === 0) && (row.room_status == 102 || row.room_status == 101)" type="danger" size="mini" @click="handleOff(row)">
97
+            下架
98
+          </el-button>
99
+          <el-button v-else type="info" size="mini" disabled @click="handleOff(row)">
100
+            已结束
101
+          </el-button>
102
+          <el-button type="primary" size="mini" @click="handleUpdate(row)">
103
+            更新
104
+          </el-button>
105
+        </template>
106
+      </el-table-column>
107
+    </el-table>
108
+
109
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
110
+  </div>
111
+</template>
112
+
113
+<script>
114
+import { fetchRoomGoodsList, publishRoomGoods, offRoomGoods, updateRoomGoods } from '@/api/live'
115
+import waves from '@/directive/waves' // waves directive
116
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
117
+
118
+export default {
119
+  name: 'ComplexTable',
120
+  components: { Pagination },
121
+  directives: { waves },
122
+  filters: {
123
+    statusFilter(status) {
124
+      const statusMap = {
125
+        0: 'success',
126
+        1: 'info',
127
+        2: 'danger'
128
+      }
129
+      return statusMap[status]
130
+    }
131
+  },
132
+  data() {
133
+    return {
134
+      list: null,
135
+      total: 0,
136
+      listLoading: true,
137
+      listQuery: {
138
+        page: 1,
139
+        num: 20
140
+      },
141
+
142
+      temp: {
143
+        goods_name: '',
144
+        price_type: '1',
145
+        price: '',
146
+        price2: ''
147
+      },
148
+
149
+      statusOptions: ['已上架', '草稿', '已下架'],
150
+      showGoodsID: false,
151
+      showWXGoodsID: false,
152
+      showRoomID: false,
153
+      inventory: 0
154
+    }
155
+  },
156
+  created() {
157
+    this.getList()
158
+  },
159
+  methods: {
160
+    getList() {
161
+      this.listLoading = true
162
+      var _self = this
163
+      fetchRoomGoodsList(this.listQuery).then(response => {
164
+        _self.list = response.data.goods_list.map(goods => {
165
+          goods.isEditable = false
166
+          return goods
167
+        })
168
+        _self.total = response.data.count
169
+        // Just to simulate the time of the request
170
+        this.listLoading = false
171
+      })
172
+    },
173
+
174
+    handleFilter() {
175
+      this.getList()
176
+    },
177
+
178
+    handleOff(row) {
179
+      var _self = this
180
+      this.$alert(`确定从${row.room_name}下架${row.goods_name}`, '下架产品', {
181
+        confirmButtonText: '下架',
182
+        callback: action => {
183
+          offRoomGoods(row).then(response => {
184
+            _self.getList()
185
+          })
186
+        }
187
+      })
188
+    },
189
+
190
+    handlePublish(row) {
191
+      var _self = this
192
+      publishRoomGoods(row).then(response => {
193
+        _self.getList()
194
+      })
195
+    },
196
+
197
+    handleUpdate(row) {
198
+      row.isEditable = true
199
+      this.inventory = row.inventory
200
+    },
201
+
202
+    handleUpdateCancel(row) {
203
+      row.isEditable = false
204
+    },
205
+
206
+    handleInventoryChanged(row) {
207
+      var _self = this
208
+      const goods = row
209
+      goods.inventory = this.inventory
210
+      updateRoomGoods(goods).then(response => {
211
+        _self.getList()
212
+      })
213
+    }
214
+  }
215
+}
216
+</script>